// 14 重载运算与类型转换
/**
 * 当运算符被用于类类型的对象时，C++语言允许我们为其指定新的含义；同时，我们也能自定义类类型之间的转换规则。和内置类型的转换一样，类类型转换隐式地将一种类型的对象转换成另一种我们所需类型的对象。
 * 当运算符作用于类类型的运算对象时，可以通过运算符重载重新定义该运算符的含义。明智地使用运算符重载能令我们的程序更易于编写和阅读。
 */

#include <iterator>
#include <vector>
#include <list>
#include <deque>
#include <forward_list>
#include <string>
#include <array>
#include <stack>
#include <queue>
#include <algorithm>
#include <numeric>
using std::swap;
using std::vector, std::list, std::deque, std::forward_list, std::string, std::array, std::stack, std::queue;
#include "../Chapter07/Sales_data.h"
#include <iostream>
using std::begin, std::cbegin, std::end, std::cend, std::find, std::accumulate, std::equal, std::fill, std::fill_n, std::back_inserter;
using std::cin, std::cout, std::endl;
using std::copy, std::replace, std::replace_copy;
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <memory>
#include <new>
using namespace std;
#include "../Chapter13/13.5.cc" // 不能编译，因为重复定义的main函数
#include "../Chapter12/12.1.6.cc" // 不能编译，因为重复定义的main函数


int main()
{
    // 14.7 成员访问运算符
    // 在迭代器类及智能指针类（参见12.1节，第400页）中常常用到解引用运算符（＊）和箭头运算符（->）。我们以如下形式向StrBlobPtr类添加这两种运算符：(见12.1.6.cc)
    // 解引用运算符首先检查curr是否仍在作用范围内，如果是，则返回curr所指元素的一个引用。箭头运算符不执行任何自己的操作，而是调用解引用运算符并返回解引用结果元素的地址。
    // 箭头运算符必须是类的成员。解引用运算符通常也是类的成员，尽管并非必须如此。
    // 值得注意的是，我们将这两个运算符定义成了const成员，这是因为与递增和递减运算符不一样，获取一个元素并不会改变StrBlobPtr对象的状态。
    // 这两个运算符的用法与指针或者vector迭代器的对应操作完全一致：
    StrBlob a1 = {"hi", "bye", "now"};
    StrBlobPtr p(a1);   // p指向a1中的vector
    *p = "okay";        // 给a1的首元素赋值
    cout << p->size() << endl;   // 打印4，这是a1首元素的大小
    cout << (*p).size() << endl; // 等价于p->size();

    // 对箭头运算符返回值的限定
    // 和大多数其他运算符一样（尽管这么做不太好），我们能令operator＊完成任何我们指定的操作。换句话说，我们可以让operator＊返回一个固定值42，或者打印对象的内容，或者其他。
    // 箭头运算符则不是这样，它永远不能丢掉成员访问这个最基本的含义。当我们重载箭头时，可以改变的是箭头从哪个对象当中获取成员，而箭头获取成员这一事实则永远不变。
    // 重载的箭头运算符必须返回类的指针或者自定义了箭头运算符的某个类的对象。




    return 0;
}